/**
 * 统一缓存管理工具类
 * 支持本地缓存和Redis缓存，优先使用本地缓存提高性能
 */
import cache from '@/plugins/cache'
import Vue from 'vue'

class CacheManager {
  constructor() {
    // 缓存键前缀
    this.CACHE_PREFIX = {
      USER: 'user_name_',
      DEPT: 'dept_name_',
      COUPON: 'coupon_name_',
      PRODUCT: 'product_name_',
      LOGISTICS: 'logistics_company_'
    }
    
    // 默认缓存时间（30分钟）
    this.CACHE_EXPIRE_TIME = 30 * 60 * 1000
    
    // 创建响应式数据存储
    this.reactiveData = Vue.observable({})
    
    // 加载状态管理
    this.loadingStates = Vue.observable({})
    
    // 正在加载的Promise存储，避免重复请求
    this.loadingPromises = new Map()
    
    // 全局加载完成回调
    this.loadingCallbacks = new Map()
  }

  /**
   * 生成缓存键
   * @param {string} prefix 前缀
   * @param {string|number} id ID
   * @returns {string} 缓存键
   */
  generateCacheKey(prefix, id) {
    return `${prefix}${id}`
  }

  /**
   * 设置缓存数据
   * @param {string} key 缓存键
   * @param {any} value 缓存值
   * @param {number} expireTime 过期时间（毫秒），默认30分钟
   */
  setCache(key, value, expireTime = this.CACHE_EXPIRE_TIME) {
    const cacheData = {
      value: value,
      timestamp: Date.now(),
      expireTime: expireTime
    }
    cache.local.setJSON(key, cacheData)
  }

  /**
   * 获取缓存数据
   * @param {string} key 缓存键
   * @returns {any} 缓存值，如果不存在或已过期返回null
   */
  getCache(key) {
    const cacheData = cache.local.getJSON(key)
    if (!cacheData) {
      return null
    }

    // 检查是否过期
    if (Date.now() - cacheData.timestamp > cacheData.expireTime) {
      cache.local.remove(key)
      return null
    }

    return cacheData.value
  }

  /**
   * 删除缓存
   * @param {string} key 缓存键
   */
  removeCache(key) {
    cache.local.remove(key)
  }

  /**
   * 清除所有指定前缀的缓存
   * @param {string} prefix 前缀
   */
  clearCacheByPrefix(prefix) {
    // 由于localStorage没有模糊匹配删除功能，这里遍历所有键
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      if (key && key.startsWith(prefix)) {
        cache.local.remove(key)
      }
    }
  }

  /**
   * 获取用户名称（带缓存）
   * @param {string|number} userId 用户ID
   * @param {Function} apiFunction 获取用户信息的API函数
   * @param {Function} onLoaded 加载完成回调函数
   * @returns {string} 用户名称
   */
  getUserName(userId, apiFunction, onLoaded = null) {
    if (!userId) return '-'

    const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.USER, userId)
    
    // 检查响应式数据
    if (this.reactiveData[cacheKey] && this.reactiveData[cacheKey] !== '加载中...') {
      return this.reactiveData[cacheKey]
    }
    
    // 检查缓存
    let userName = this.getCache(cacheKey)
    if (userName) {
      Vue.set(this.reactiveData, cacheKey, userName)
      Vue.set(this.loadingStates, cacheKey, false)
      if (onLoaded) onLoaded(userName)
      return userName
    }

    // 如果已经在加载中，返回现有Promise
    if (this.loadingPromises.has(cacheKey)) {
      Vue.set(this.reactiveData, cacheKey, '加载中...')
      Vue.set(this.loadingStates, cacheKey, true)
      if (onLoaded) {
        this.loadingPromises.get(cacheKey).then(result => onLoaded(result))
      }
      return this.reactiveData[cacheKey]
    }

    // 设置初始值和加载状态
    Vue.set(this.reactiveData, cacheKey, '加载中...')
    Vue.set(this.loadingStates, cacheKey, true)

    // 创建加载Promise
    const loadingPromise = apiFunction(userId).then(response => {
      userName = response.data && response.data.userName ? response.data.userName : '-'
      this.setCache(cacheKey, userName)
      Vue.set(this.reactiveData, cacheKey, userName)
      Vue.set(this.loadingStates, cacheKey, false)
      
      // 触发Vue的响应式更新
      this.$forceUpdate && this.$forceUpdate()
      
      if (onLoaded) onLoaded(userName)
      return userName
    }).catch(error => {
      console.warn('获取用户信息失败:', userId, error)
      this.setCache(cacheKey, '-', 5 * 60 * 1000) // 错误结果缓存5分钟
      Vue.set(this.reactiveData, cacheKey, '-')
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded('-')
      return '-'
    }).finally(() => {
      this.loadingPromises.delete(cacheKey)
    })

    this.loadingPromises.set(cacheKey, loadingPromise)
    return this.reactiveData[cacheKey]
  }

  /**
   * 获取部门名称（带缓存）
   * @param {string|number} deptId 部门ID
   * @param {Function} apiFunction 获取部门信息的API函数
   * @param {Function} onLoaded 加载完成回调函数
   * @returns {string} 部门名称
   */
  getDeptName(deptId, apiFunction, onLoaded = null) {
    if (!deptId) return '-'

    const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.DEPT, deptId)
    
    // 检查响应式数据
    if (this.reactiveData[cacheKey] && this.reactiveData[cacheKey] !== '加载中...') {
      return this.reactiveData[cacheKey]
    }
    
    // 检查缓存
    let deptName = this.getCache(cacheKey)
    if (deptName) {
      Vue.set(this.reactiveData, cacheKey, deptName)
      Vue.set(this.loadingStates, cacheKey, false)
      if (onLoaded) onLoaded(deptName)
      return deptName
    }

    // 如果已经在加载中，返回现有Promise
    if (this.loadingPromises.has(cacheKey)) {
      Vue.set(this.reactiveData, cacheKey, '加载中...')
      Vue.set(this.loadingStates, cacheKey, true)
      if (onLoaded) {
        this.loadingPromises.get(cacheKey).then(result => onLoaded(result))
      }
      return this.reactiveData[cacheKey]
    }

    // 设置初始值和加载状态
    Vue.set(this.reactiveData, cacheKey, '加载中...')
    Vue.set(this.loadingStates, cacheKey, true)

    // 创建加载Promise
    const loadingPromise = apiFunction(deptId).then(response => {
      deptName = response.data && response.data.deptName ? response.data.deptName : '-'
      this.setCache(cacheKey, deptName)
      Vue.set(this.reactiveData, cacheKey, deptName)
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded(deptName)
      return deptName
    }).catch(error => {
      console.warn('获取部门信息失败:', deptId, error)
      this.setCache(cacheKey, '-', 5 * 60 * 1000) // 错误结果缓存5分钟
      Vue.set(this.reactiveData, cacheKey, '-')
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded('-')
      return '-'
    }).finally(() => {
      this.loadingPromises.delete(cacheKey)
    })

    this.loadingPromises.set(cacheKey, loadingPromise)
    return this.reactiveData[cacheKey]
  }

  /**
   * 获取优惠券名称（带缓存）
   * @param {string|number} couponId 优惠券ID
   * @param {Function} apiFunction 获取优惠券信息的API函数
   * @param {Function} onLoaded 加载完成回调函数
   * @returns {string} 优惠券名称
   */
  getCouponName(couponId, apiFunction, onLoaded = null) {
    if (!couponId) return '-'

    const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.COUPON, couponId)
    
    // 检查响应式数据
    if (this.reactiveData[cacheKey] && this.reactiveData[cacheKey] !== '加载中...') {
      return this.reactiveData[cacheKey]
    }
    
    // 检查缓存
    let couponName = this.getCache(cacheKey)
    if (couponName) {
      Vue.set(this.reactiveData, cacheKey, couponName)
      Vue.set(this.loadingStates, cacheKey, false)
      if (onLoaded) onLoaded(couponName)
      return couponName
    }

    // 如果已经在加载中，返回现有Promise
    if (this.loadingPromises.has(cacheKey)) {
      Vue.set(this.reactiveData, cacheKey, '加载中...')
      Vue.set(this.loadingStates, cacheKey, true)
      if (onLoaded) {
        this.loadingPromises.get(cacheKey).then(result => onLoaded(result))
      }
      return this.reactiveData[cacheKey]
    }

    // 设置初始值和加载状态
    Vue.set(this.reactiveData, cacheKey, '加载中...')
    Vue.set(this.loadingStates, cacheKey, true)

    // 创建加载Promise
    const loadingPromise = apiFunction(couponId).then(response => {
      couponName = response.data && response.data.couponName ? response.data.couponName : '-'
      this.setCache(cacheKey, couponName)
      Vue.set(this.reactiveData, cacheKey, couponName)
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded(couponName)
      return couponName
    }).catch(error => {
      console.warn('获取优惠券信息失败:', couponId, error)
      this.setCache(cacheKey, '-', 5 * 60 * 1000) // 错误结果缓存5分钟
      Vue.set(this.reactiveData, cacheKey, '-')
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded('-')
      return '-'
    }).finally(() => {
      this.loadingPromises.delete(cacheKey)
    })

    this.loadingPromises.set(cacheKey, loadingPromise)
    return this.reactiveData[cacheKey]
  }

  /**
   * 获取商品名称（带缓存）
   * @param {string|number} productId 商品ID
   * @param {Function} apiFunction 获取商品信息的API函数
   * @param {Function} onLoaded 加载完成回调函数
   * @returns {string} 商品名称
   */
  getProductName(productId, apiFunction, onLoaded = null) {
    if (!productId) return '-'

    const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.PRODUCT, productId)
    
    // 检查响应式数据
    if (this.reactiveData[cacheKey] && this.reactiveData[cacheKey] !== '加载中...') {
      return this.reactiveData[cacheKey]
    }
    
    // 检查缓存
    let productName = this.getCache(cacheKey)
    if (productName) {
      Vue.set(this.reactiveData, cacheKey, productName)
      Vue.set(this.loadingStates, cacheKey, false)
      if (onLoaded) onLoaded(productName)
      return productName
    }

    // 如果已经在加载中，返回现有Promise
    if (this.loadingPromises.has(cacheKey)) {
      Vue.set(this.reactiveData, cacheKey, '加载中...')
      Vue.set(this.loadingStates, cacheKey, true)
      if (onLoaded) {
        this.loadingPromises.get(cacheKey).then(result => onLoaded(result))
      }
      return this.reactiveData[cacheKey]
    }

    // 设置初始值和加载状态
    Vue.set(this.reactiveData, cacheKey, '加载中...')
    Vue.set(this.loadingStates, cacheKey, true)

    // 创建加载Promise
    const loadingPromise = apiFunction(productId).then(response => {
      productName = response.data && response.data.productName ? response.data.productName : '-'
      this.setCache(cacheKey, productName)
      Vue.set(this.reactiveData, cacheKey, productName)
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded(productName)
      return productName
    }).catch(error => {
      console.warn('获取商品信息失败:', productId, error)
      this.setCache(cacheKey, '-', 5 * 60 * 1000) // 错误结果缓存5分钟
      Vue.set(this.reactiveData, cacheKey, '-')
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded('-')
      return '-'
    }).finally(() => {
      this.loadingPromises.delete(cacheKey)
    })

    this.loadingPromises.set(cacheKey, loadingPromise)
    return this.reactiveData[cacheKey]
  }

  /**
   * 获取物流公司名称（带缓存）
   * @param {string|number} companyId 物流公司ID
   * @param {Function} apiFunction 获取物流公司信息的API函数
   * @param {Function} onLoaded 加载完成回调函数
   * @returns {string} 物流公司名称
   */
  getLogisticsCompanyName(companyId, apiFunction, onLoaded = null) {
    if (!companyId) return '-'

    const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.LOGISTICS, companyId)
    
    // 检查响应式数据
    if (this.reactiveData[cacheKey] && this.reactiveData[cacheKey] !== '加载中...') {
      return this.reactiveData[cacheKey]
    }
    
    // 检查缓存
    let companyName = this.getCache(cacheKey)
    if (companyName) {
      Vue.set(this.reactiveData, cacheKey, companyName)
      Vue.set(this.loadingStates, cacheKey, false)
      if (onLoaded) onLoaded(companyName)
      return companyName
    }

    // 如果已经在加载中，返回现有Promise
    if (this.loadingPromises.has(cacheKey)) {
      Vue.set(this.reactiveData, cacheKey, '加载中...')
      Vue.set(this.loadingStates, cacheKey, true)
      if (onLoaded) {
        this.loadingPromises.get(cacheKey).then(result => onLoaded(result))
      }
      return this.reactiveData[cacheKey]
    }

    // 设置初始值和加载状态
    Vue.set(this.reactiveData, cacheKey, '加载中...')
    Vue.set(this.loadingStates, cacheKey, true)

    // 创建加载Promise
    const loadingPromise = apiFunction(companyId).then(response => {
      companyName = response.data && response.data.expName ? response.data.expName : '-'
      this.setCache(cacheKey, companyName)
      Vue.set(this.reactiveData, cacheKey, companyName)
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded(companyName)
      return companyName
    }).catch(error => {
      console.warn('获取物流公司信息失败:', companyId, error)
      this.setCache(cacheKey, '-', 5 * 60 * 1000) // 错误结果缓存5分钟
      Vue.set(this.reactiveData, cacheKey, '-')
      Vue.set(this.loadingStates, cacheKey, false)
      
      if (onLoaded) onLoaded('-')
      return '-'
    }).finally(() => {
      this.loadingPromises.delete(cacheKey)
    })

    this.loadingPromises.set(cacheKey, loadingPromise)
    return this.reactiveData[cacheKey]
  }

  /**
   * 等待所有加载完成
   * @param {Array} cacheKeys 需要等待的缓存键数组
   * @returns {Promise} 所有加载完成的Promise
   */
  async waitForAllLoaded(cacheKeys) {
    const promises = []
    
    for (const cacheKey of cacheKeys) {
      if (this.loadingPromises.has(cacheKey)) {
        promises.push(this.loadingPromises.get(cacheKey))
      }
    }
    
    if (promises.length > 0) {
      await Promise.allSettled(promises)
    }
  }

  /**
   * 检查是否有正在加载的项目
   * @param {Array} cacheKeys 需要检查的缓存键数组
   * @returns {boolean} 是否有正在加载的项目
   */
  hasLoadingItems(cacheKeys) {
    return cacheKeys.some(cacheKey => this.loadingStates[cacheKey] === true)
  }

  /**
   * 获取加载状态
   * @param {string} cacheKey 缓存键
   * @returns {boolean} 是否正在加载
   */
  isLoading(cacheKey) {
    return this.loadingStates[cacheKey] === true
  }

  /**
   * 强制刷新Vue组件
   * @param {Object} vueInstance Vue组件实例
   */
  forceUpdate(vueInstance) {
    if (vueInstance && vueInstance.$forceUpdate) {
      vueInstance.$forceUpdate()
    }
  }

  /**
   * 批量预加载数据
   * @param {Array} items 需要预加载的项目数组，格式：[{type: 'user', id: 1, apiFunction: fn}, ...]
   * @returns {Promise} 预加载完成的Promise
   */
  async preloadData(items) {
    const promises = []
    
    for (const item of items) {
      const { type, id, apiFunction } = item
      let cacheKey
      
      switch (type) {
        case 'user':
          cacheKey = this.generateCacheKey(this.CACHE_PREFIX.USER, id)
          break
        case 'dept':
          cacheKey = this.generateCacheKey(this.CACHE_PREFIX.DEPT, id)
          break
        case 'coupon':
          cacheKey = this.generateCacheKey(this.CACHE_PREFIX.COUPON, id)
          break
        case 'product':
          cacheKey = this.generateCacheKey(this.CACHE_PREFIX.PRODUCT, id)
          break
        case 'logistics':
          cacheKey = this.generateCacheKey(this.CACHE_PREFIX.LOGISTICS, id)
          break
        default:
          continue
      }
      
      // 如果缓存中没有数据且没有正在加载，则开始预加载
      if (!this.getCache(cacheKey) && !this.loadingPromises.has(cacheKey)) {
        const promise = this.loadData(type, id, apiFunction)
        promises.push(promise)
      }
    }
    
    if (promises.length > 0) {
      await Promise.allSettled(promises)
    }
  }

  /**
   * 内部方法：加载数据
   * @param {string} type 数据类型
   * @param {string|number} id ID
   * @param {Function} apiFunction API函数
   * @returns {Promise} 加载Promise
   */
  async loadData(type, id, apiFunction) {
    switch (type) {
      case 'user':
        return new Promise((resolve) => {
          this.getUserName(id, apiFunction, resolve)
        })
      case 'dept':
        return new Promise((resolve) => {
          this.getDeptName(id, apiFunction, resolve)
        })
      case 'coupon':
        return new Promise((resolve) => {
          this.getCouponName(id, apiFunction, resolve)
        })
      case 'product':
        return new Promise((resolve) => {
          this.getProductName(id, apiFunction, resolve)
        })
      case 'logistics':
        return new Promise((resolve) => {
          this.getLogisticsCompanyName(id, apiFunction, resolve)
        })
      default:
        return Promise.resolve('-')
    }
  }

  /**
   * 批量获取用户名称（带缓存）
   * @param {Array} userIds 用户ID数组
   * @param {Function} apiFunction 获取用户信息的API函数
   * @returns {Promise<Object>} 用户ID到用户名称的映射对象
   */
  async batchGetUserNames(userIds, apiFunction) {
    const result = {}
    const uncachedIds = []

    // 先从缓存中获取
    for (const userId of userIds) {
      if (!userId) {
        result[userId] = '-'
        continue
      }

      const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.USER, userId)
      const cachedName = this.getCache(cacheKey)
      
      if (cachedName) {
        result[userId] = cachedName
      } else {
        uncachedIds.push(userId)
      }
    }

    // 批量获取未缓存的数据
    for (const userId of uncachedIds) {
      try {
        const userName = await this.getUserName(userId, apiFunction)
        result[userId] = userName
      } catch (error) {
        result[userId] = '-'
      }
    }

    return result
  }

  /**
   * 批量获取部门名称（带缓存）
   * @param {Array} deptIds 部门ID数组
   * @param {Function} apiFunction 获取部门信息的API函数
   * @returns {Promise<Object>} 部门ID到部门名称的映射对象
   */
  async batchGetDeptNames(deptIds, apiFunction) {
    const result = {}
    const uncachedIds = []

    // 先从缓存中获取
    for (const deptId of deptIds) {
      if (!deptId) {
        result[deptId] = '-'
        continue
      }

      const cacheKey = this.generateCacheKey(this.CACHE_PREFIX.DEPT, deptId)
      const cachedName = this.getCache(cacheKey)
      
      if (cachedName) {
        result[deptId] = cachedName
      } else {
        uncachedIds.push(deptId)
      }
    }

    // 批量获取未缓存的数据
    for (const deptId of uncachedIds) {
      try {
        const deptName = await this.getDeptName(deptId, apiFunction)
        result[deptId] = deptName
      } catch (error) {
        result[deptId] = '-'
      }
    }

    return result
  }

  /**
   * 清除所有缓存
   */
  clearAllCache() {
    Object.values(this.CACHE_PREFIX).forEach(prefix => {
      this.clearCacheByPrefix(prefix)
    })
  }

  /**
   * 获取缓存统计信息
   * @returns {Object} 缓存统计信息
   */
  getCacheStats() {
    const stats = {
      total: 0,
      byPrefix: {}
    }

    Object.entries(this.CACHE_PREFIX).forEach(([name, prefix]) => {
      let count = 0
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (key && key.startsWith(prefix)) {
          count++
        }
      }
      stats.byPrefix[name] = count
      stats.total += count
    })

    return stats
  }
}

// 创建单例实例
const cacheManager = new CacheManager()

export default cacheManager
